home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Mail / EnhanceMail.1.3 / Source / Preferences.m < prev    next >
Encoding:
Text File  |  1996-04-09  |  15.4 KB  |  511 lines

  1. /* -*-C-*-
  2. *******************************************************************************
  3. *
  4. * File:         Preferences.m
  5. * RCS:          $Header: /usr/local/lib/cvs/EnhanceMail/Preferences.m,v 1.1.1.23 1996/04/09 16:18:58 cedman Exp $
  6. * Description:  
  7. * Author:       Carl Edman
  8. * Created:      Wed Nov  1 09:58:01 1995
  9. * Modified:     Tue Apr  9 11:46:04 1996 (Carl Edman) cedman@capitalist.princeton.edu
  10. * Language:     C
  11. * Package:      N/A
  12. * Status:       Experimental (Do Not Distribute)
  13. *
  14. * (C) Copyright 1995, but otherwise this file is perfect freeware.
  15. *
  16. *******************************************************************************
  17. */
  18.  
  19. #define PREFEXTERN
  20. #import "Preferences.h"
  21. #undef PREFEXTERN
  22. #import "EnhanceMail.h"
  23. #import "XFace.h"
  24. #import "XImageURL.h"
  25. #import "regexp.h"
  26. #import <ctype.h>
  27. #import <math.h>
  28. #import <netdb.h>
  29.  
  30. #define MSG_OK NXLoadLocalizedStringFromTableInBundle("Buttons", nil, "OK", NULL)
  31. #define MSG_BAD_XFACE NXLocalizedStringFromTableInBundle("Localizable", EnhanceBundle, "%s does not contain monochrome 48x48 image.", NULL, Error message for bad XFace)
  32. #define MSG_BAD_REGEXP NXLocalizedStringFromTableInBundle("Localizable", EnhanceBundle, "%s is not a valid regular expression.", NULL, Error message for bad Regexp)
  33.  
  34. #define DEFAULT_QUOTE_INTRO NXLocalizedStringFromTableInBundle("Localizable", EnhanceBundle, "You wrote:", NULL, Default introduction to quotes in replies)
  35.  
  36. static struct PrefDefault
  37.    {
  38.    struct PrefDefault *next;
  39.    enum { bool=1, string, integer, color } type;
  40.    union
  41.       {
  42.       BOOL *bool;
  43.       const char **string;
  44.       int *integer;
  45.       NXColor *color;
  46.       } location;
  47.    id control;
  48.    char name[0];
  49.    } *prefroot=0;
  50.  
  51. static HashTable *PanelHash=nil;
  52. static NXImage *delete_image=nil;
  53. static id XImageURLButton=nil;
  54. static id XFaceButton=nil;
  55.  
  56. @implementation EnhancePreferences
  57. + finishLoading:(struct mach_header *)header
  58.    {
  59.    id pref;
  60.    char path[MAXPATHLEN+1];
  61.    
  62.    if (EnhanceBundle==0) EnhanceBundle=[NXBundle bundleForClass:[self class]];
  63.    [self poseAs:[self superclass]];
  64.  
  65.    if ([EnhanceBundle getPath:path forResource:"delete" ofType:"tiff"])
  66.       delete_image=[[NXImage alloc] initFromFile:path];
  67.    
  68.    pref=[Preferences new];
  69.  
  70.    if ([EnhanceBundle getPath:path forResource:"EnhancePreferences" ofType:"nib"])
  71.       [NXApp loadNibFile:path owner:pref];
  72.  
  73.    [pref addPanel:NXGetNamedObject("Quoting_Box2",pref)];
  74.    [pref addPanel:NXGetNamedObject("Images_Box2",pref)];
  75.    [pref addPanel:NXGetNamedObject("Options_Box2",pref)];
  76.    
  77.    EnhanceQuoteReplies=NO;
  78.    EnhanceQuoteColoring=NO;
  79.    EnhanceLaunchMailboxes=NO;
  80.    EnhanceLaunchAddresses=NO;
  81.    EnhanceInsertSignature=NO;
  82.    EnhanceRepliesWithOriginals=NO;
  83.    EnhanceRestoreDeletesDraft=NO;
  84.    EnhanceInsertXFace=NO;
  85.    EnhanceInsertXImageURL=NO;
  86.    EnhanceShowXImageURL=NO;
  87.    EnhanceShowXFace=NO;
  88.    EnhanceBackSpaceBackPages=NO;
  89.    EnhanceAutoCompact=NO;
  90.    EnhanceAutoSpellCheck=NO;
  91.    EnhanceQuotePrefix="> %0";
  92.    EnhanceQuoteRegex="^[>:# ]*[>:#] ?";
  93.    EnhanceSignatureSeparator="---\n";
  94.    EnhanceSignatureFilename=".signature";
  95.    EnhanceQuoteIntro=DEFAULT_QUOTE_INTRO;
  96.    EnhanceQuoteColor=NX_COLORBLACK;
  97.    EnhanceXFace="";
  98.    EnhanceXImageURL="";
  99.    EnhanceFlagReplies=NO;
  100.    EnhanceHTTPProxy="";
  101.  
  102.    [pref registerBool:"QuoteReplies"
  103.              location:&EnhanceQuoteReplies
  104.               control:"Quoting_Box2_Quoting_Quote Replies"];
  105.    [pref registerBool:"QuoteColoring"
  106.              location:&EnhanceQuoteColoring
  107.               control:"Quoting_Box2_Quoting_Color Quotes"];
  108.    [pref registerBool:"LaunchMailboxes"
  109.              location:&EnhanceLaunchMailboxes
  110.               control:"Options_Box2_Other_Form_Open Mailboxes Window on Launch"];
  111.    [pref registerBool:"LaunchAddresses"
  112.              location:&EnhanceLaunchAddresses
  113.               control:"Options_Box2_Other_Form_Open Addresses Window on Launch"];
  114.    [pref registerBool:"InsertSignature"
  115.              location:&EnhanceInsertSignature
  116.               control:"Quoting_Box2_Signatures_Insert Signatures"];
  117.    [pref registerBool:"RepliesWithOriginals"
  118.              location:&EnhanceRepliesWithOriginals
  119.               control:"Options_Box2_Other_Form_Keep Replies with Originals"];
  120.    [pref registerBool:"RestoreDeletesDraft"
  121.              location:&EnhanceRestoreDeletesDraft
  122.               control:0];
  123.    [pref registerBool:"InsertXFace"
  124.              location:&EnhanceInsertXFace
  125.               control:"Images_Box2_XFace_Form_Send XFace"];
  126.    [pref registerBool:"ShowXFace"
  127.              location:&EnhanceShowXFace
  128.               control:"Images_Box2_XFace_Form_Show XFace"];
  129.    [pref registerBool:"InsertXImageURL"
  130.              location:&EnhanceInsertXImageURL
  131.               control:"Images_Box2_XImageURL_Form_Send XImageURL"];
  132.    [pref registerBool:"ShowXImageURL"
  133.              location:&EnhanceShowXImageURL
  134.               control:"Images_Box2_XImageURL_Form_Show XImageURL"];
  135.    [pref registerBool:"BackSpaceBackPages"
  136.              location:&EnhanceBackSpaceBackPages
  137.               control:0];
  138.    [pref registerBool:"AutoCompact"
  139.              location:&EnhanceAutoCompact
  140.               control:"Options_Box2_Other_Form_Automatically compact mailboxes"];
  141.    [pref registerBool:"AutoSpellCheck"
  142.              location:&EnhanceAutoSpellCheck
  143.               control:"Options_Box2_Other_Form_Automatically spell check messages"];
  144.    [pref registerString:"QuoteIntro"
  145.                location:&EnhanceQuoteIntro
  146.                 control:"Quoting_Box2_Quoting_Form_Introduction"];
  147.    [pref registerString:"QuotePrefix"
  148.                location:&EnhanceQuotePrefix
  149.                 control:"Quoting_Box2_Quoting_Form_Prefix"];
  150.    [pref registerString:"QuoteRegex"
  151.                location:&EnhanceQuoteRegex
  152.                 control:"Quoting_Box2_Quoting_Form_Regex"];
  153.    [pref registerString:"XFace"
  154.                location:&EnhanceXFace
  155.                 control:"Images_Box2_XFace_Path"];
  156.    [pref registerString:"XImageURL"
  157.                location:&EnhanceXImageURL
  158.                 control:"Images_Box2_XImageURL_Path"];
  159.    [pref registerString:"SignatureFilename"
  160.                location:&EnhanceSignatureFilename
  161.                 control:"Quoting_Box2_Signatures_Form_Filename"];
  162.    [pref registerString:"SignatureSeparator"
  163.                location:&EnhanceSignatureSeparator
  164.                 control:"Quoting_Box2_Signatures_Form_Separator"];
  165.    [pref registerString:"HTTPProxy"
  166.                location:&EnhanceHTTPProxy
  167.                 control:"Images_Box2_XImageURL_Proxy"];
  168.    [pref registerColor:"QuoteColor"
  169.               location:&EnhanceQuoteColor
  170.                control:"Quoting_Box2_Quoting_Color"];
  171.    [pref registerBool:"FlagReplies"
  172.              location:&EnhanceFlagReplies
  173.               control:"Options_Box2_Other_Form_Flag Replies"];
  174.  
  175.    XFaceButton=NXGetNamedObject("Images_Box2_XFace_Box_Image",pref);
  176.    XImageURLButton=NXGetNamedObject("Images_Box2_XImageURL_Box_Image",pref);
  177.    
  178.    [pref upLoad];
  179.    return self;
  180.    }
  181.  
  182. - (void)downLoad
  183.    {
  184.    struct PrefDefault *pd;
  185.    const char *appname, *tmp;
  186.    char buf[1024];
  187.  
  188.    appname=[NXApp appName];
  189.  
  190.    for(pd=prefroot;pd;pd=pd->next) if (pd->control!=nil) switch (pd->type)
  191.       {
  192.     case bool:
  193.       *pd->location.bool=[pd->control state];
  194.       break;
  195.     case string:
  196.       *pd->location.string=[pd->control stringValue];
  197.       break;
  198.     case integer:
  199.       *pd->location.integer=[pd->control intValue];
  200.       break;
  201.     case color:
  202.       *pd->location.color=[pd->control color];
  203.       break;
  204.       }
  205.  
  206.    for(pd=prefroot;pd;pd=pd->next) switch (pd->type)
  207.       {
  208.     case bool:
  209.       NXWriteDefault(appname,pd->name,*(pd->location.bool) ? "YES" : "NO");
  210.       break;
  211.     case string:
  212.       NXWriteDefault(appname,pd->name,*(pd->location.string));
  213.       break;
  214.     case integer:
  215.       sprintf(buf,"%d",*(pd->location.integer));
  216.       NXWriteDefault(appname,pd->name,buf);
  217.       break;
  218.     case color:
  219.       if (tmp=NXColorName(*(pd->location.color)))
  220.          NXWriteDefault(appname,pd->name,tmp);
  221.       else
  222.          {
  223.          float red,green,blue;
  224.          
  225.          NXConvertColorToRGB(*(pd->location.color),&red,&green,&blue);
  226.          sprintf(buf,"RGB%02x%02x%02x",(int)rint(red*0xff),(int)rint(green*0xff),(int)rint(blue*0xff));
  227.          NXWriteDefault(appname,pd->name,buf);
  228.          }
  229.       break;
  230.       }
  231.    
  232.    [super downLoad];
  233.    }
  234.  
  235. - (void)upLoad
  236.    {
  237.    int i;
  238.    struct PrefDefault *pd;
  239.    const char *appname, *value, *c;
  240.    id colorlistlist=[NXColorList availableColorLists];
  241.  
  242.    [super upLoad];
  243.    NXUpdateDefaults();
  244.    appname=[NXApp appName];
  245.  
  246.    for(pd=prefroot;pd;pd=pd->next) if (value=NXReadDefault(appname,pd->name)) switch (pd->type)
  247.       {
  248.     case bool:
  249.       if (strcasecmp(value,"YES")==0)
  250.          *(pd->location.bool)=YES;
  251.       else if (strcasecmp(value,"NO")==0)
  252.          *(pd->location.bool)=NO;
  253.       else
  254.          [self logWarning:"Boolean default %s given bad value \"%s\".",appname,pd->name,value];
  255.       break;
  256.     case string:
  257.       *(pd->location.string)=value;
  258.       break;
  259.     case integer:
  260.       for(c=value;isspace(*c);c++);
  261.       for(i=0;isdigit(*c);c++) i=i*10+(*c-'0');
  262.       while(isspace(*c)) c++;
  263.       if (*c=='\0')
  264.          *(pd->location.integer)=i;
  265.       else
  266.          [self logWarning:"Integer default %s given bad value \"%s\".",appname,pd->name,value];
  267.       break;
  268.     case color:
  269.       i=-1;
  270.       if ((strncmp(value,"RGB",3)==0)&&(strlen(value)==9))
  271.          {
  272.          for(c=value+3,i=0;*c;c++)
  273.             {
  274.             if (*c>='0' && *c<='9')      i=16*i+*c-'0';
  275.             else if (*c>='a' && *c<='f') i=16*i+*c-('a'-10);
  276.             else if (*c>='A' && *c<='F') i=16*i+*c-('A'-10);
  277.             else break;
  278.             }
  279.          
  280.          if (*c)
  281.             i=-1;
  282.          else
  283.             {
  284.             *(pd->location.color)=NXConvertRGBToColor(((i>>16)&0xff)/255.0,((i>>8)&0xff)/255.0,(i&0xff)/255.0);
  285.             i=0;
  286.             }
  287.          }
  288.       
  289.       if (i<0) for(i=[colorlistlist count]-1;i>=0;i--)
  290.          {
  291.          if (NXFindColorNamed([[colorlistlist objectAt:i] name],value,pd->location.color))
  292.             break;
  293.          }
  294.       
  295.       if (i<0)
  296.          [self logWarning:"Color default %s given bad value \"%s\".",appname,pd->name,value];
  297.       break;
  298.       }
  299.  
  300.    for(pd=prefroot;pd;pd=pd->next) if (pd->control!=nil) switch (pd->type)
  301.       {
  302.     case bool:
  303.       [pd->control setState:*(pd->location.bool)];
  304.       break;
  305.     case string:
  306.       [pd->control setStringValue:*(pd->location.string)];
  307.       break;
  308.     case integer:
  309.       [pd->control setIntValue:*(pd->location.integer)];
  310.       break;
  311.     case color:
  312.       [pd->control setColor:*(pd->location.color)];
  313.       break;
  314.       }
  315.    
  316.    if (XFaceButton!=nil)
  317.       {
  318.       NXImage *image;
  319.       NXRect r;
  320.  
  321.       [XFaceButton getBounds:&r];
  322.       image=[[NXImage alloc] initFromFile:EnhanceXFace xFaceSize:&r.size];
  323.       if (image==nil) image=delete_image;
  324.       [XFaceButton setImage:image];
  325.       }
  326.  
  327.    if (XImageURLButton!=nil)
  328.       {
  329.       NXImage *image;
  330.       NXRect r;
  331.  
  332.       [XImageURLButton getBounds:&r];
  333.       image=[[NXImage alloc] initURL:EnhanceXImageURL];
  334.       if (image==nil) image=delete_image;
  335.       [image setScalable:YES];
  336.       [image setSize:&r.size];
  337.       [XImageURLButton setImage:image];
  338.       }
  339.    }
  340.  
  341. - controlFor:(const void *)location
  342.    {
  343.    struct PrefDefault *pd;
  344.    for(pd=prefroot;pd;pd=pd->next)
  345.       if ((pd->location.string)==location) return pd->control;
  346.    
  347.    return nil;
  348.    }
  349.  
  350. - addPanel:panel
  351.    {
  352.    id cell;
  353.    id popuplist;
  354.    int tag;
  355.    
  356.    if (panel==nil) return nil;
  357.    
  358.    popuplist=[[viewButton cell] target];
  359.    for(tag=0;[popuplist findCellWithTag:tag]!=nil;tag++);
  360.    
  361.    cell=[popuplist addItem:[[panel window] title]];
  362.    [cell setTarget:self];
  363.    [cell setAction:@selector(changeView:)];
  364.    [cell setTag:tag];
  365.  
  366.    if (PanelHash==nil) PanelHash=[[HashTable alloc] initKeyDesc:"i" valueDesc:"@"];
  367.    [PanelHash insertKey:(const void *)tag value:panel];
  368.    return self;
  369.    }
  370.  
  371. - registerBool:(const char *)name location:(BOOL *)loc control:(const char *)con
  372.    {
  373.    struct PrefDefault *pd=malloc(sizeof(*pd)+strlen(name)+1);
  374.    pd->next=prefroot;
  375.    pd->type=bool;
  376.    pd->location.bool=loc;
  377.    pd->control=con ? NXGetNamedObject(con,self) : nil;
  378.    if ((pd->control!=nil)
  379.        && ([pd->control respondsTo:@selector(setEnabled:)]))
  380.       [pd->control setEnabled:YES];
  381.    strcpy(pd->name,name);
  382.    prefroot=pd;
  383.    return self;
  384.    }
  385.  
  386. - registerString:(const char *)name location:(const char **)loc control:(const char *)con;
  387.    {
  388.    struct PrefDefault *pd=malloc(sizeof(*pd)+strlen(name)+1);
  389.    pd->next=prefroot;
  390.    pd->type=string;
  391.    pd->location.string=loc;
  392.    pd->control=con ? NXGetNamedObject(con,self) : nil;
  393.    if ((pd->control!=nil)
  394.        && ([pd->control respondsTo:@selector(setEnabled:)]))
  395.       [pd->control setEnabled:YES];
  396.    strcpy(pd->name,name);
  397.    prefroot=pd;
  398.    return self;
  399.    }
  400.  
  401. - registerInteger:(const char *)name location:(int *)loc control:(const char *)con
  402.    {
  403.    struct PrefDefault *pd=malloc(sizeof(*pd)+strlen(name)+1);
  404.    pd->next=prefroot;
  405.    pd->type=integer;
  406.    pd->location.integer=loc;
  407.    pd->control=con ? NXGetNamedObject(con,self) : nil;
  408.    if ((pd->control!=nil)
  409.        && ([pd->control respondsTo:@selector(setEnabled:)]))
  410.       [pd->control setEnabled:YES];
  411.    strcpy(pd->name,name);
  412.    prefroot=pd;
  413.    return self;
  414.    }
  415.  
  416. - registerColor:(const char *)name location:(NXColor *)loc control:(const char *)con
  417.    {
  418.    struct PrefDefault *pd=malloc(sizeof(*pd)+strlen(name)+1);
  419.    pd->next=prefroot;
  420.    pd->type=color;
  421.    pd->location.color=loc;
  422.    pd->control=con ? NXGetNamedObject(con,self) : nil;
  423.    if ((pd->control!=nil)
  424.        && ([pd->control respondsTo:@selector(setEnabled:)]))
  425.       [pd->control setEnabled:YES];
  426.    strcpy(pd->name,name);
  427.    prefroot=pd;
  428.    return self;
  429.    }
  430.  
  431. - changeView:sender
  432.    {
  433.    id ret,item,panel,ogeneralview;
  434.    int tag;
  435.  
  436.    if (((item=[viewButton selectedPopUpItem])==nil)
  437.        ||((tag=[item tag])==0)
  438.        ||(PanelHash==nil)
  439.        ||((panel=[PanelHash valueForKey:(const void *)tag])==nil))
  440.       return [super changeView:sender];
  441.  
  442.    ogeneralview=generalView;
  443.    generalView=panel;
  444.    [item setTag:0];
  445.    ret=[super changeView:sender];
  446.    [item setTag:tag];
  447.    generalView=ogeneralview;
  448.  
  449.    return ret;
  450.    }
  451.  
  452. - noteChangeXFace:sender
  453.    {
  454.    id XFace=[self controlFor:&EnhanceXFace];
  455.    
  456.    if (XFace && XFaceButton)
  457.       {
  458.       NXRect r;
  459.       NXImage *image;
  460.       const char *val;
  461.       
  462.       val=[XFace stringValue];
  463.       [XFaceButton getBounds:&r];
  464.       image=[[NXImage alloc] initFromFile:val xFaceSize:&r.size];
  465.       if (image==nil) image=delete_image;
  466.       [XFaceButton setImage:image];
  467.       }
  468.    
  469.    return [super noteChange:sender];
  470.    }
  471.  
  472. - noteChangeXImageURL:sender
  473.    {
  474.    id XImageURL=[self controlFor:&EnhanceXImageURL];
  475.    
  476.    if (XImageURL && XImageURLButton)
  477.       {
  478.       NXRect r;
  479.       NXImage *image;
  480.       const char *val;
  481.       
  482.       val=[XImageURL stringValue];
  483.       [XImageURLButton getBounds:&r];
  484.       image=[[NXImage alloc] initURL:val];
  485.       if (image==nil) image=delete_image;
  486.       [image setScalable:YES];
  487.       [image setSize:&r.size];
  488.       [XImageURLButton setImage:image];
  489.       }
  490.    
  491.    return [self noteChange:sender];
  492.    }
  493.  
  494. - setXFace:sender
  495.    {
  496.    id open;
  497.    const char *const types[] = { "tiff", 0 };
  498.    id XFaceC=[self controlFor:&EnhanceXFace];
  499.    
  500.    if (((XFaceC=[self controlFor:&EnhanceXFace])==nil)
  501.        || ((open=[OpenPanel new])==nil)
  502.        || ([open allowMultipleFiles:NO]==nil)
  503.        || ([open runModalForDirectory:[XFaceC stringValue] file:0 types:types]!=NX_OKTAG)
  504.        || ([open filename]==0))
  505.       return nil;
  506.  
  507.    [XFaceC setStringValue:[open filename]];
  508.    return [self noteChangeXFace:sender];
  509.    }
  510. @end
  511.